#include "../../../include/graphics/gl/GLShader.hpp"
#include "../../../include/error/Exception.hpp"
using namespace klas;
using namespace graphics;
using namespace gl;

#include <iostream>
#include <fstream>
using namespace std;

GLShader::GLShader(string file, eShaderType shaderType)
{
  create(file, shaderType);
}

GLShader::~GLShader()
{
  destroy();
}

bool GLShader::create(string file, eShaderType shaderType)
{
  // Make sure we have no shader
  destroy();

  // Set the shader
  if(shaderType == FRAGMENT_SHADER)
    m_shaderType = GL_FRAGMENT_SHADER;
  if(shaderType == VERTEX_SHADER)
    m_shaderType = GL_VERTEX_SHADER;

  // Generate the shader
  m_shaderID = glCreateShader(m_shaderType);

  
  /* load in source data */
  int length;
	char *buffer;

	ifstream is;
  is.clear();
  is.open((file.c_str()), ios::binary);
	if (is.fail()) {
    throw error::Exception("GLShader::create - cannot load the file");
	}

	// get length of file
	is.seekg(0, ios::end);
	length = is.tellg();
	is.seekg(0, ios::beg);

	// allocate memory:
	buffer = new char[length+1];

	// read data as a block:
	is.read(buffer, length);
	is.close();

  // set the shader source
	buffer[length] = '\0';
	const char *source = buffer;
	glShaderSource(m_shaderID, 1, &source, NULL);

	delete[] buffer;
  /* done loading source data */

  // compile the shader
  glCompileShader(m_shaderID);


  // print debug log
  {
    int length = 0;
	  char *infoLog;

	  glGetShaderiv(m_shaderID, GL_INFO_LOG_LENGTH, &length);
	  if (length > 1) {
		  infoLog = new char[length];
		  glGetShaderInfoLog(m_shaderID, length, NULL, infoLog);
		  cout << infoLog;
		  delete infoLog;
	  }
  }
}

bool GLShader::destroy()
{
  glDeleteShader(m_shaderID);
  m_shaderID = 0;

  return true;
}